home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Tools / Utility / LogLibrary 950622 / Src / LogLibrary.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  29.1 KB  |  722 lines  |  [TEXT/MPCC]

  1. /*                                        LogLibrary.h                                */
  2. /*
  3.  * LogLibrary.h
  4.  * Copyright © 1992-95 Apple Computer Inc. All Rights Reserved.
  5.  * Programmed by Martin Minow,
  6.  *    Internet:    minow@apple.com
  7.  *    AppleLink:    MINOW
  8.  * Version of May 25, 1995
  9.  */
  10. #ifndef __LogLibrary__
  11. #define __LogLibrary__
  12. /*
  13.  * Usage:
  14.  *    PowerPC (native):
  15.  *        Include "LogLibrary.h" in all compilations.
  16.  *        Either compile the LogLibrary functions or include LogLibrary (shared library).
  17.  *    68000 emulation
  18.  *        Include "LogLibrary.h" in all compilations.
  19.  *        Compile LogLibrary.c, LogConvertTimestamp.c, and LogFormatTimestamp.c
  20.  *        (or include an object).
  21.  *        Make LogLibrary known to the executing program, possibly by storing
  22.  *        it in the Extensions folder.
  23.  *
  24.  * Edit History
  25.  *    94.10.16 MM        Revised (throughly) from the Audit library to take advantage of
  26.  *                    the new I/O architecture. The library name has been changed from
  27.  *                    Audit to DriverLog. The driver log is named through the System
  28.  *                    Name Registry. These functions are (currently) only available in
  29.  *                    PowerPC.
  30.  *    94.12.12 MM        Finished converting to LogLibrary, added Mixed Mode support so
  31.  *                    the (Power PC) library may be called from 68000 code.
  32.  *    95.02.03 MM        • Changed WriteLogEntry, StoreLogEntry, and ReadLogEntry to return
  33.  *                    OSErr's (to distinguish between semaphore interlock and other
  34.  *                    errors). This will allow a non-interrupt application to loop
  35.  *                    while the semaphore is interlocked, though this is not trivial.
  36.  *                    • Removed the StoreString function (now inlined).
  37.  *                    • Removed the lost data counter and entry. Sequence gaps can
  38.  *                    best be determined by watching the atomic sequence counter.
  39.  *                    • Use IncrementAtomic to update the sequence counter. This will
  40.  *                    also count data lost if the semaphore is interlocked.
  41.  *                    • StoreLogEntry stores the sequence counter and timestamp into
  42.  *                    the caller's LogEntryRecord: it is not called with a const
  43.  *                    LogEntryPtr.
  44.  * 95.03.31 MM        Added 68000-callable UpTime, removed UpTime from ReadLogEntry and
  45.  *                    CopyLogRecordEntry. LogConvertTimestamp doesn't need this.
  46.  * 1995.04.07    MM    Some compilers mis-handle functions returning structures. Store
  47.  *                    UpTime returned values in a volatile local variable before using
  48.  *                    them in a function call.
  49.  * 1995.04.11    MM    Ensure that the Code Fragment is loaded into the System Heap.
  50.  * 1995.04.29    MM    Split into LogLibrary (PPC) and LogLibrary68 (68000). This
  51.  *                    was done for the benefit of the MacsBug dcmd. This change
  52.  *                    resulted in a significant simplification of the code as all
  53.  *                    of the cross-architecture code was moved to LogLibrary68.c.
  54.  * 1995.05.25    MM    Some minor cleanups (parameters marked "const"). Removed all
  55.  *                    dependencies on the Name Registry. The underlying Create
  56.  *                    routine uses a SecondaryInterruptHandler to prevent two
  57.  *                    asynchronous tasks from adding the same record.
  58.  *
  59.  * Note: because Pascal does not support variable-length calling sequences, the
  60.  * WriteLogEntry function may only be called from C. Pascal programs must format the
  61.  * LogEntryRecord and call StoreLogEntry directly.
  62.  */
  63. /*
  64.  * To create an log library record, a driver, application, or other code segment calls
  65.  * MakeLogRecord(). This is the only function that accesses the memory manager (but
  66.  * see the note on 68000's below). The record is created by the PoolAllocateResident
  67.  * routine and must be called from task level. If the log has already been created, it
  68.  * returns a pointer to that log record.
  69.  *
  70.  * MakeLogRecord() must be called in a context that can allocate memory. The first
  71.  * call from a 68000 architecture module must be able to load a shared library.
  72.  *
  73.  * To log data, call the WriteLogEntry() routine, normally using one of the formatting
  74.  * macros.
  75.  *
  76.  * To read the next entry from the log, call the ReadLogEntry() routine.
  77.  *
  78.  * Once created, a log persists until system restart. The problem is that many
  79.  * routines might have grabbed the log address from the name registry, so deleting
  80.  * it from the registry is insufficient.
  81.  *
  82.  * There are a few other routines, but they aren't that important.
  83.  *
  84.  * A reader application processes log entries as follows.
  85.  *
  86.  *         Str255                timeText, dataText;
  87.  *        LogRecordPtr        logRecordPtr;
  88.  *        LogEntryPtr            logEntryPtr;
  89.  *        DateTimeRec            eventTime;
  90.  *        UInt32                nanoseconds;
  91.  * 
  92.  *        MyOpenLogOutputFile();
  93.  *        logPtr = GetLogRecordPtr("MyLogRecord");
  94.  *        if (logPtr != NULL) {
  95.  *            while (gQuitNow == FALSE) {
  96.  *                ProcessOneEvent();
  97.  *                for (i = 0; i < 10; i++) {
  98.  *                    if (ReadLogEntry(logPtr, &logEntry) != noErr)
  99.  *                        break;
  100.  *                    else {
  101.  *                        ConvertLogEntryTimestamp(&logEntry, &eventTime, &nanoseconds);
  102.  *                        FormatLogEntryTimestamp(timeText, &eventTime, nanoseconds);
  103.  *                        FormatLogEntryData(&logEntry, dataText);
  104.  *                        printf("%.*s: %.*s\n",
  105.  *                            timeText[0], &timeText[1],
  106.  *                            dataText[0], &dataText[1]
  107.  *                        );
  108.  *                    }
  109.  *                }
  110.  *            }
  111.  *        }
  112.  *        ExitToShell();
  113.  */
  114.  
  115. #ifndef SystemSevenOrLater
  116. #define SystemSevenOrLater    1
  117. #endif
  118.  
  119. #include <stdarg.h>
  120. #ifndef THINK_C /* Temp until headers stabalize */
  121. #include <MixedMode.h>
  122. #include <Types.h>
  123. #include <OSUtils.h>
  124. #include <DriverServices.h>
  125. #endif
  126.  
  127. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  128.  * Public definitions for the LogLibrary.
  129.  *
  130.  * We can store kLogEntryDataSize longwords in each entry. This is the maximum
  131.  * that we can store, given 3 bits per format value.
  132.  */
  133. #define kLogEntryDataSize        10
  134. /*
  135.  * Boolean32 is a Boolean stored in a longword. This prevents Think vs. MPW
  136.  * variable confusion.
  137.  */
  138. typedef UInt32                    Boolean32;
  139. /*
  140.  * Define the LogRecord name.
  141. */
  142. enum {
  143.     kLogRecordNameBufSize = 32,    /* Includes the terminating NUL    */
  144.     kLogNameTerminator    = '\0'
  145. };
  146. typedef char LogRecordNameByte, *LogRecordNamePtr, LogRecordNameBuf[kLogRecordNameBufSize];
  147.  
  148. /*
  149.  * Each log record entry contains the following information:
  150.  *        eventTime        The system UpTime value at the time the data was collected.
  151.  *        sequence        The ordinal index of this entry. This will always increment.
  152.  *                        (If you log one entry per microsecond, it will wrap around
  153.  *                        after about 70 minutes).
  154.  *        idCode            A longword that uniquely identifies the log entry (i.e.,
  155.  *                        who logged it). This is provided by the WriteLogEntry caller.
  156.  *        format            A longword that describes the format of the log data.
  157.  *        data[10]        Ten longwords that contain the entry-unique information.
  158.  *                        The actual count is defined by the format longword.
  159.  * upTime and sequence are maintained by LogLibrary routines, while the other
  160.  * parameters are copied from the WriteLogEntry parameters.
  161.  */
  162. #if defined(powerc) || defined(__powerc)
  163. #pragma option align=mac68K
  164. #endif
  165. struct LogEntryRecord {
  166.     AbsoluteTime        eventTime;        /* UpTime() at SaveLogEntry call            */
  167.     UInt32                sequence;        /* Entry number (monotomically increasing)    */
  168.     OSType                idCode;            /* Why are we logging -- set by caller        */
  169.     UInt32                format;            /* Format of the data (see below)            */
  170.     UInt32                data[kLogEntryDataSize];    /* The data itself                */
  171. };
  172. #if defined(powerc) || defined(__powerc)
  173. #pragma options align=reset
  174. #endif
  175. typedef struct LogEntryRecord LogEntryRecord, *LogEntryPtr;
  176. /*
  177.  * These flags control data formatting. Note: because data is passed using
  178.  * variable-length argument list conventions and we want the code to work
  179.  * compatably on both Think and MPW, all numeric parameters must be passed as
  180.  * "long" or "unsigned long." For example, to pass an OSErr code, do
  181.  *        WriteLogEntry(
  182.  *            'fubr',
  183.  *            LogFormat1(kLogFormatSigned),
  184.  *            (signed long) statusCode
  185.  *        );
  186.  */
  187. enum {
  188.     /*
  189.      * Parameters to the LogFormat macro.
  190.      */
  191.     kLogFormatSigned            = 0,        /* Signed long                            */
  192.     kLogFormatUnsigned            = 1,        /* Unsigned (decimal)                    */
  193.     kLogFormatHex                = 2,        /* Unsigned (hex + 'char')                */
  194.     kLogFormatAddress            = 3,        /* Unsigned hex only                    */
  195.     kLogFormatReserved4            = 4,        /* Unused                                */
  196.     kLogFormatReserved5            = 5,        /* Unused                                */
  197.     kLogFormatString            = 6,        /* String (last format)                    */
  198.     kLogFormatEnd                = 7,        /* End signal (no data)                    */
  199.     /*
  200.      * kLogFormatShift must be large enough to shift all format codes. All data
  201.      * format codes must fit into a single longword.
  202.      */
  203.     kLogFormatShift                = 3,
  204.     kLogFormatMask                = (1 << kLogFormatShift) - 1
  205. };
  206. #if ((kLogFormatShift * kLogEntryDataSize) > 32)
  207.     << (kLogFormatShift * kLogEntryDataSize) must be <= 32 bits (longword size) >>
  208. #endif
  209.  
  210. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  211.  * This section should be regarded as "private" to the LogLibrary. Applications
  212.  * that use the library never need to reference (or dereference) these structures.
  213.  * Although the content of the structures is shown explicitly, applications should
  214.  * treat these structures as "opaque" and "subject to change without notice" in
  215.  * future Macintosh operating system releases.
  216.  *
  217.  */
  218. /*
  219.  * The LogRecord iterator contents are private to the library.
  220.  */
  221. #if defined(powerc) || defined(__powerc)
  222. #pragma option align=mac68K
  223. #endif
  224. struct LogRecordIter {
  225.     struct LogRecord    *logRecordPtr;
  226. };
  227. #if defined(powerc) || defined(__powerc)
  228. #pragma options align=reset
  229. #endif
  230. typedef struct LogRecordIter LogRecordIter, *LogRecordIterPtr;
  231.  
  232. #if defined(powerc) || defined(__powerc)
  233. #pragma option align=mac68K
  234. #endif
  235. struct LogRecord {
  236.     struct LogRecord    *logRecordLink;        /* -> Next LogRecord instance            */
  237.     LogRecordNameBuf    logName;            /* This LogRecord's identification        */
  238.     volatile UInt32        semaphore;            /* In critical section if non-zero        */
  239.     volatile UInt32        lostLockCounter;    /* Can't enter critical section            */
  240.     volatile UInt32        sequenceCounter;    /* Absolute sequence counter            */
  241.     volatile UInt32        flags;                /* Logging & lost data flags            */
  242.     volatile UInt32        entryPutIndex;        /* Where to store the next record        */
  243.     volatile UInt32        entryGetIndex;        /* Where to retrieve the next record    */
  244.     volatile UInt32        entryMaxIndex;        /* Actual number of log entries            */
  245.     LogEntryRecord        entries[1];            /* Log entries are stored here            */
  246. };
  247. #if defined(powerc) || defined(__powerc)
  248. #pragma options align=reset
  249. #endif
  250. typedef struct LogRecord LogRecord, *LogRecordPtr;
  251. /*
  252.  * Values for the flags variable in the LogDataRecord. These are private to the
  253.  * LogData library and dcmd display routine.
  254.  */
  255. enum {
  256.     kLogDataEnabledMask            = (1L <<  0),    /* Enable logging if set            */
  257.     kLogDataPreserveFirstMask    = (1L <<  1),    /* Preserve first entry if set        */
  258.     kLogDataRecordUpTimeMask    = (1L <<  2),    /* Don't record UpTime if set        */
  259.     kLogDataWrapAroundMask        = (1L <<  3)    /* Log has wrapped around once        */
  260. };
  261.  
  262. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  263.  * The following information is public.
  264.  *
  265.  * The LogFormat macro stores the format word.
  266.  */
  267. #define LogFormat(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9)    \
  268.     (  (f0)                                            \
  269.      | ((f1) << (kLogFormatShift * 1))                \
  270.      | ((f2) << (kLogFormatShift * 2))                \
  271.      | ((f3) << (kLogFormatShift * 3))                \
  272.      | ((f4) << (kLogFormatShift * 4))                \
  273.      | ((f5) << (kLogFormatShift * 5))                \
  274.      | ((f6) << (kLogFormatShift * 6))                \
  275.      | ((f7) << (kLogFormatShift * 7))                \
  276.      | ((f8) << (kLogFormatShift * 8))                \
  277.      | ((f9) << (kLogFormatShift * 9))                \
  278.     )
  279. #define LogFormat1(f0)                                                            \
  280.     LogFormat(                                                                    \
  281.         (f0),          kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  282.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  283.         kLogFormatEnd, kLogFormatEnd                                            \
  284.     )
  285. #define LogFormat2(f0, f1)                                                        \
  286.     LogFormat(                                                                    \
  287.         (f0),          (f1),          kLogFormatEnd, kLogFormatEnd,                \
  288.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  289.         kLogFormatEnd, kLogFormatEnd                                            \
  290.     )
  291. #define LogFormat3(f0, f1, f2)                                                    \
  292.     LogFormat(                                                                    \
  293.         (f0),          (f1),          (f2),          kLogFormatEnd,                \
  294.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  295.         kLogFormatEnd, kLogFormatEnd                                            \
  296.     )
  297. #define LogFormat4(f0, f1, f2, f3)                                                \
  298.     LogFormat(                                                                    \
  299.         (f0),          (f1),          (f2),          (f3),                        \
  300.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  301.         kLogFormatEnd, kLogFormatEnd                                            \
  302.     )
  303. #define LogFormat5(f0, f1, f2, f3, f4)                                            \
  304.     LogFormat(                                                                    \
  305.         (f0),          (f1),          (f2),          (f3),                        \
  306.         (f4),            kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,            \
  307.         kLogFormatEnd, kLogFormatEnd                                            \
  308.     )
  309. #define LogFormat6(f0, f1, f2, f3, f4, f5)                                        \
  310.     LogFormat(                                                                    \
  311.         (f0),          (f1),          (f2),          (f3),                        \
  312.         (f4),          (f5),          kLogFormatEnd, kLogFormatEnd,                \
  313.         kLogFormatEnd, kLogFormatEnd                                            \
  314.     )
  315. #define LogFormat7(f0, f1, f2, f3, f4, f5, f6)                                    \
  316.     LogFormat(                                                                    \
  317.         (f0),          (f1),          (f2),          (f3),                        \
  318.         (f4),          (f5),          (f6),          kLogFormatEnd,                \
  319.         kLogFormatEnd, kLogFormatEnd                                            \
  320.     )
  321. #define LogFormat8(f0, f1, f2, f3, f4, f5, f6, f7)                                \
  322.     LogFormat(                                                                    \
  323.         (f0),          (f1),          (f2),          (f3),                        \
  324.         (f4),          (f5),          (f6),          (f7),                        \
  325.         kLogFormatEnd, kLogFormatEnd                                            \
  326.     )
  327. #define LogFormat9(f0, f1, f2, f3, f4, f5, f6, f7, f8)                            \
  328.     LogFormat(                                                                    \
  329.         (f0),          (f1),          (f2),          (f3),                        \
  330.         (f4),          (f5),          (f6),          (f7),                        \
  331.         (f8),          kLogFormatEnd                                            \
  332.     )
  333. #define LogFormat10(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9)                        \
  334.     LogFormat(                                                                    \
  335.         (f0),          (f1),          (f2),          (f3),                        \
  336.         (f4),          (f5),          (f6),          (f7),                        \
  337.         (f8),          (f9)                                                        \
  338.     )
  339. /*
  340.  * These are popular format types.
  341.  */
  342. #define LogNoFormat    (LogFormat1(kLogFormatEnd))
  343. #define LogStringFormat    LogFormat1(kLogFormatString)
  344. #define LogStatusFormat    LogFormat2(kLogFormatSigned, kLogFormatString)
  345.  
  346. /*
  347.  * The application or code segment calls the following functions to access LogRecord 
  348.  * records MakeLogRecord must be called from a non-interrupt execution level as it may
  349.  * allocate memory and store information into the System Name Registry. MakeLogRecord
  350.  * or GetLogRecordPtr must be called before calling any other LogRecord function. 
  351.  *
  352.  * GetLogRecordPtr can generally be called either from noninterrupt or secondary
  353.  * execution level, however the first call from a 68000 architecture module must be
  354.  * able to load a shared library and, potentially, allocate memory.
  355.  *
  356.  * All other routines may be called from any execution level.
  357.  */
  358.  
  359. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  360.  * LogLibrary68Initialize
  361.  *
  362.  * This function is only called from a 68000 module to "soft-link" to the LogLibrary.
  363.  * It calls the Code Fragment Manager and, implicitly, requires access to the file
  364.  * system and may allocate memory. This function does nothing if called from a
  365.  * PowerPC native module.
  366.  */
  367. pascal OSErr            LogLibrary68Initialize(void);
  368.  
  369. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  370.  * MakeLogRecord
  371.  *
  372.  * The first time this function is called after the system is started, it creates a
  373.  * log record for this name. The log is initially enabled, and deletes overflow at the
  374.  * start. It thus retains the *end* of the log -- this is useful for ongoing logging,
  375.  * but may lose the start of a disaster sequence (as it records the flow of errors
  376.  * through the system, rather than the intial cause.
  377.  *
  378.  * LogRecordNamePtr must define a non-null string. nEntries must be non-zero.
  379.  * The logRecordNamePtr "name" is reserved to the Name Registry. Don't use it.
  380.  *
  381.  * This function must be called in a context that can allocate memory. The first call
  382.  * from a 68000 architecture module must be able to access the Code Fragment Manager.
  383.  *
  384.  * Return the LogRecordPtr for this log, or NULL if unsuccessful.
  385.  */
  386. pascal LogRecordPtr            MakeLogRecord(
  387.         const LogRecordNamePtr    logRecordNamePtr,        /* Log name (C-string)        */
  388.         UInt32                    nEntries                /* Number of Log entries    */
  389.     );
  390.  
  391. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  392.  * GetLogRecordPtr
  393.  *
  394.  * Return a pointer to the log record for a specified name. Returns NULL if it was
  395.  * not found (WriteLogEntry, etc. will not choke). The first call from a 68000
  396.  * module must be able to access the Code Fragment Manager.
  397.  */
  398. pascal LogRecordPtr            GetLogRecordPtr(
  399.         const LogRecordNamePtr    logRecordNamePtr        /* Log name (C-string)        */
  400.     );
  401.  
  402. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  403.  * LogString
  404.  *
  405.  * LogString calls WriteLogEntry with a single Pascal string argument. Following ANSI
  406.  * C conventions, it is provided as a macro and as a function. The function may be
  407.  * called from Pascal.
  408.  */
  409. #define LogString(ptr, idCode, string) \
  410.         WriteLogEntry((ptr), (idCode), LogStringFormat, string)
  411. pascal OSErr                (LogString)(
  412.         LogRecordPtr            logRecordPtr,            /* This log record            */
  413.         OSType                    idCode,                    /* Entry identifier            */
  414.         ConstStr255Param        string                    /* The datum                */
  415.     );
  416.  
  417. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  418.  * LogStatusString
  419.  *
  420.  * LogStatusString calls WriteLogEntry with the status and string values. It is
  421.  * provided as a macro and as a function.
  422.  */
  423. #define LogStatusString(ptr, idCode, status, string) (    \
  424.         WriteLogEntry(                                    \
  425.             (ptr),                                        \
  426.             (idCode),                                    \
  427.             LogStatusFormat,                            \
  428.             (signed long) (status),                        \
  429.             string                                        \
  430.         )                                                \
  431.     )
  432. pascal OSErr                (LogStatusString)(
  433.         LogRecordPtr            logRecordPtr,            /* This log record            */
  434.         OSType                    idCode,                    /* Entry identifier            */
  435.         OSErr                    status,                    /* Status error code        */
  436.         ConstStr255Param        string                    /* The datum                */
  437.     );
  438.  
  439. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  440.  * WriteLogEntry
  441.  *
  442.  * Write a LogRecord entry if logging is enabled and there is space in the log.
  443.  *    logRecordPtr Identifies this log.
  444.  *    idCode        A user-controlled value, by convention an OSType (4-byte character)
  445.  *                that identifies this entry. The display application prints it. Note
  446.  *                that, on the Macintosh, an OSType can be coerced from/to any longword
  447.  *                scalar (such as an address) without loss of data. This may be useful
  448.  *                for user-written display applications.
  449.  *    format        A longword that specifies the format of the remaining data. Use the
  450.  *                value LogStringFormat if the only datum is a Pascal string; use the
  451.  *                value LogStatusFormat if you are logging an OSErr and an accompaning
  452.  *                string; otherwise, use the LogFormat macro to create the value.
  453.  *    ...            Additional data as needed. Note that all data must be specified as, or
  454.  *                coerced to longwords (StringPtr, address, or long). Naturally short
  455.  *                integers such as Booleans or OSErr codes must be explicitly cast to
  456.  *                long. This is needed because of compiler options regarding data
  457.  *                format lengths.
  458.  * WriteLogData will always be in the current instruction architecture as you cannot
  459.  * make a MixedMode call with a variable-length argument list. Also, WriteLogData
  460.  * cannot be called from Pascal for the same reason.
  461.  *
  462.  * Return values:
  463.  *    noErr        Normal completion or logging was disabled.
  464.  *    writErr        The entry could not be stored because the LogRecord was full. This
  465.  *                can usually be ignored.
  466.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  467.  *                locked -- presumably by an asynchronous process. The caller may
  468.  *                wish to try the operation again, perhaps after a short delay.
  469.  */
  470. OSErr                        WriteLogEntry(
  471.         LogRecordPtr            logRecordPtr,            /* This log record            */
  472.         OSType                    idCode,                    /* Entry identifier            */
  473.         UInt32                    format,                    /* Format bits                */
  474.         ...                                                /* Additional data, if any    */
  475.     );
  476.  
  477. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  478.  * StoreLogEntry
  479.  *
  480.  * Store a formatted LogEntryRecord in the log. This is the only routine that
  481.  * writes the log entry. Normally, it is only called by WriteLogData. This function
  482.  * will store the following data into the caller's LogEntryRecord (even if logging
  483.  * was disabled or the log was full):
  484.  *        sequence    This entry sequence counter.
  485.  *        eventTime    UpTime when this record was added to the LogRecord.
  486.  *
  487.  * Return values:
  488.  *    noErr        Normal completion or logging was disabled.
  489.  *    writErr        The entry could not be stored because the LogRecord was full. This
  490.  *                can usually be ignored.
  491.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  492.  *                locked -- presumably by an asynchronous process. The caller may
  493.  *                wish to try the operation again, perhaps after a short delay.
  494.  */
  495. pascal OSErr                StoreLogEntry(
  496.         LogRecordPtr            logRecordPtr,            /* This log record            */
  497.         const LogEntryPtr        logEntryPtr                /* Gets this entry            */
  498.     );
  499.  
  500. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  501.  * ReadLogEntry
  502.  *
  503.  * Read the next LogRecord entry. This returns a copy of the entry, if one is
  504.  * available. ReadLogEntry also returns the UpTime value when it was called. This
  505.  * is needed by 68000-based applications as the function is only available from the
  506.  * Power PC native DriverServices library.
  507.  *
  508.  * Return values:
  509.  *    noErr        Normal completion or logging was disabled.
  510.  *    readErr        The entry could not be stored because the LogRecord was empty
  511.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  512.  *                locked -- presumably by an asynchronous process. The caller may
  513.  *                wish to try the operation again, perhaps after a short delay.
  514.  */
  515. pascal OSErr                ReadLogEntry(
  516.         LogRecordPtr            logRecordPtr,            /* This log record            */
  517.         LogEntryPtr                thisLogEntry            /* Store entry here            */
  518.     );
  519.  
  520. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  521.  * EnableLogRecord
  522.  *
  523.  * Enable/disable logging. Returns the old logging state.
  524.  */
  525. pascal Boolean32            EnableLogRecord(
  526.         LogRecordPtr            logRecordPtr,            /* This log record            */
  527.         Boolean32                enableLogging            /* TRUE to enable logging    */
  528.     );
  529.  
  530. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  531.  * PreserveLogRecord
  532.  *
  533.  * Set the preserveFirst flag. Returns the old flag value. 
  534.  */
  535. pascal Boolean32            PreserveLogRecord(
  536.         LogRecordPtr            logRecordPtr,            /* This log record            */
  537.         Boolean32                preserveFirst            /* TRUE to preserve start    */
  538.     );
  539.  
  540. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  541.  * EnableLogUpTime
  542.  *
  543.  * Enable/disable recording of UpTime when WriteLogRecord. Returns the old state.
  544.  * UpTime generally would be left in its original, enabled, state. The state may be
  545.  * set FALSE to minimize the time needed to log data. If set FALSE, times will be
  546.  * recorded as zero.
  547.  */
  548. pascal Boolean32            EnableLogUpTime(
  549.         LogRecordPtr            logRecordPtr,            /* This log record            */
  550.         Boolean32                enableUpTime            /* TRUE to enable UpTime    */
  551.     );
  552.  
  553. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  554.  * GetLogSemaphoreLostCounter
  555.  *
  556.  * Because the log library uses a "lossy" algorithm to maintain exclusive access to
  557.  * the critical section, there is a very slight possibility that two processes will
  558.  * try to access the log record at the same time. In this case, ReadLogEntry will
  559.  * stall (loop) and eventually succeed, while WriteLogEntry will lose the datum, and
  560.  * increment the logLostCounter.
  561.  */
  562. pascal UInt32                GetLogSemaphoreLostCounter(
  563.         LogRecordPtr            logRecordPtr            /* This log record            */
  564.     );
  565.  
  566. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  567.  * FormatLogEntryData
  568.  *
  569.  * This function is in LogFormat.c - it formats an entry into a single line
  570.  * that is stored in the result. Note: only the data is formatted: the timestamp
  571.  * is not processed. This function may be called from a non-application context;
  572.  * It does not require a MixedMode switch.
  573.  */
  574. pascal void                    FormatLogEntryData(
  575.         const LogEntryPtr        thisLogEntry,            /* Format this entry        */
  576.         StringPtr                result
  577.     );
  578.  
  579. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  580.  * LogConvertTimestamp
  581.  *
  582.  * This function is in LogConvertTimestamp.c - it formats the timestamp into civil
  583.  * ("clock") time, returning the result in a DateTimeRec and an associated residual
  584.  * number of nanoseconds. This routine calls Macintosh Toolbox services. It is not
  585.  * in the shared library. Calling sequence:
  586.  *        LogEntryRecord        thisLogEntry;
  587.  *        UInt32                thisCivilTime;
  588.  *        DateTimeRec            thisDateTime;
  589.  *        UInt32                residualNanoseconds;
  590.  *
  591.  *        if (ReadLogEntry(myLogRecordPtr, &thisLogEntry)) {
  592.  *            LogConvertTimestamp(
  593.  *                &thisLogEntry,
  594.  *                &thisDateTime,
  595.  *                &residualNanoseconds
  596.  *            );
  597.  *        }
  598.  * thisCivilTime will have the civil time (seconds since 1904) when the entry was
  599.  * stored into the log. thisDateTime will have the corresponding civil date
  600.  * (Year, Month, Day, Hour, Minute, Second)
  601.  */
  602. pascal void                    LogConvertTimestamp(
  603.         const LogEntryPtr        logEntryPtr,            /* Current log entry        */
  604.         DateTimeRec                *eventDateTime,            /* Year, Month, Day etc.    */
  605.         UInt32                    *residualNanoseconds    /* Fractional second        */
  606.     );
  607.  
  608. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  609.  * FormatLogEntryTimestamp
  610.  *
  611.  * Format a converted log entry timestamp (prepared by ConvertLogEntryTimestamp). The
  612.  * result is appended to result as a fixed-length string: "yyyy.mm.dd hh.mm.ss.msec"
  613.  * FormatLogEntryTimestamp does not use the system date formatting routines. Note
  614.  * that the fractional seconds are truncated to the nearest lower millisecond, even
  615.  * though nanosecond precision is potentially available. This function does not
  616.  * require a MixedMode switch.
  617.  */
  618. pascal void                    FormatLogEntryTimestamp(
  619.         StringPtr                result,                    /* Append to this string    */
  620.         const DateTimeRec        *eventDateTime,            /* Year, Month, Day etc.    */
  621.         UInt32                    residualNanoseconds        /* Fractional second        */
  622.     );
  623.  
  624. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  625.  * LogRecord utilities.
  626.  *
  627.  * These three functions are used to locate all registered log records. They may be
  628.  * used for a display utility or MacsBug dcmd. Applications call them as follows:
  629.  *
  630.  *    LogRecordIter            cookie;
  631.  *
  632.  *    if (LogRecordIterateCreate(&cookie) == noErr) {
  633.  *        while ((logRecordPtr = LogRecordIterate(&cookie)) != NULL) {
  634.  *            ... Process this LogRecord, the name may be extracted from the record ...
  635.  *        }
  636.  *        LogRecordIterateDispose(&cookie);
  637.  *    }
  638.  */
  639. pascal OSErr                LogRecordIterateCreate(
  640.         LogRecordIterPtr        cookie
  641.     );
  642. pascal LogRecordPtr            LogRecordIterate(
  643.         LogRecordIterPtr        cookie
  644.     );
  645. pascal void                    LogRecordIterateDispose(
  646.         LogRecordIterPtr        cookie
  647.     );
  648.  
  649. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  650.  * CopyLogRecord
  651.  *
  652.  * This function copies the permanent part of the LogRecord (srcLogRecordPtr) to a
  653.  * caller-designated area (dstLogRecordPtr). It is only for the benefit of the DCMD.
  654.  * It returns noErr if successful, paramErr if either the source or destination parameters
  655.  * are incorrect, or a Shared Library Manager error. This function ignores the interlock
  656.  * semaphore. Thus, it may return inconstent data. It does not copy the first LogRecordEntry.
  657.  *
  658.  * Only the DCMD is permitted to call this function!
  659.  */
  660. pascal OSErr                CopyLogRecordInfo(
  661.         const LogRecordPtr        srcLogRecordPtr,
  662.         LogRecordPtr            dstLogRecordPtr
  663.     );
  664.  
  665. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  666.  * CopyLogEntry
  667.  *
  668.  * Copy the specified LogRecord entry. This returns a copy of the entry. It is only
  669.  * used by the DCMD to snapshot a LogRecord.
  670.  *
  671.  * Return values:
  672.  *    noErr        Normal completion or logging was disabled.
  673.  *    readErr        The entry could not be stored because the LogRecord was empty.
  674.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  675.  *                locked -- presumably by an asynchronous process. The caller may
  676.  *                wish to try the operation again, perhaps after a short delay.
  677.  */
  678. pascal OSErr                CopyLogEntry(
  679.         LogRecordPtr            logRecordPtr,            /* This log record            */
  680.         UInt32                    getIndex,                /* This entry index            */
  681.         LogEntryPtr                thisLogEntry            /* Store entry here            */
  682.     );
  683.  
  684. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  685.  * LogUpTime
  686.  *
  687.  * This is the DriverServicesLibrary UpTime function, callable from 68000. It is
  688.  * called, once, by LogConvertTimestamp.
  689.  *
  690.  * Return values
  691.  *    resultPtr    AbsoluteTime
  692.  */
  693. pascal void                    LogUpTime(
  694.         AbsoluteTime            *resultPtr
  695.     );
  696. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  697.  * LogGetTimeBaseInfo
  698.  *
  699.  * This is the DriverServicesLibrary UpTime function, callable from 68000. It returns
  700.  * only those values that LogConvertTimestamp needs.
  701.  *
  702.  * Return values
  703.  *    upTimeNumerator        Needed for our AbsoluteToNanoseconds
  704.  *    upTimeDenominator    Needed for our AbsoluteToNanoseconds
  705.  */
  706. pascal void                    LogGetTimeBaseInfo(
  707.         UInt32                    *upTimeNumerator,
  708.         UInt32                    *upTimeDenominator
  709.     );
  710.  
  711. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  712.  * LogInitializeSharedLibraries
  713.  *
  714.  * This is called by the dcmd to bind the 68000 library to the Name Registry library.
  715.  * It is only needed by LogLibrary68.c and must be called in an "application" context
  716.  * as it allocates memory and accesses the file system.
  717.  */
  718. pascal void                    LogInitializeSharedLibraries(void);
  719.  
  720. #endif    /* __LogLibrary__    */
  721.  
  722.